package com.googlecode.imule.redundant;

/**
 * - UDP_chat class serves both server and client functionality.
 * - Start of program requires choosing between 'client' and server'
 * - Currently server must be started before client
 * - Client is able to send multiple messages to server, 
 *   server is only able to send messages to itself...
 * @author Mike Solomon
 * @created 27/02/08
 * @modified 28/02/08
 */

import java.io.*;
import java.net.*;

public class UDP_chat {

	public static final String ipAddress = "127.0.0.1";
	// public static final int inPort = 5678;
	// public static final int outPort = 4445;
	public String msg = "";

	private DatagramSocket OutSocket;// = new DatagramSocket();
	// private DatagramSocket InSocket; // = new DatagramSocket(7777);
	private DatagramPacket inPacket, outPacket;

	/** The thread that listens for incoming messages */
	private myListener listener;

	private byte[] outBuf, inBuf;

	public UDP_chat() {
		// outBuf = msg.getBytes();
		inBuf = new byte[1024];

		try {
			OutSocket = new DatagramSocket();
			DatagramSocket InSocket = new DatagramSocket();
			inPacket = new DatagramPacket(inBuf, inBuf.length);
			// outPacket = new DatagramPacket(outBuf, outBuf.length,
			// InetAddress.getByName(ipAddress), port);
			// inPacket = new DatagramPacket( inBuf, inBuf.length );

			listener = new myListener(InSocket, inPacket);
			listener.start();

		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public int getInPacketPort() {
		return inPacket.getPort();
	}

	public void sendMsg(String message) {
		try {
			outBuf = message.getBytes();
			outPacket = new DatagramPacket(outBuf, outBuf.length, InetAddress
					.getByName(ipAddress), OutSocket.getLocalPort());
			OutSocket.send(outPacket);
		} catch (Exception e) {
			System.out.println(e);
		}
	}

	public static void main(String args[]) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String message = "";

		System.out.println("Who are you?");
		String ID = br.readLine();
		UDP_chat chat = new UDP_chat();

		if (ID.equalsIgnoreCase("server")) {
			System.out.println("<<<<<---- Server starting ---->>");
			try {
				while (true) {
					// chat.receiveMsg();
					message = br.readLine();
					if (message.equalsIgnoreCase("quit")) {
						System.exit(0);
					}
					chat.outPacket.setPort(chat.getInPacketPort());
					chat.sendMsg(message);
				}
			} catch (Exception e) {
				System.out.println(e);
			}
		} else if (ID.equalsIgnoreCase("client")) {
			System.out.println("<<---- Client starting ---->>");

			try {

				while (true) {
					while (!message.equalsIgnoreCase("quit")) {
						message = br.readLine();
						chat.sendMsg(message);
						if (message.equalsIgnoreCase("quit")) {
							System.exit(0);
						}
					}
				}
			} catch (Exception e) {
				System.out.println(e);
			}
		} else {
			System.out
					.println("You're stupid and not a server or a client. Go away");
		}

	}
}

class myListener extends Thread {
	/** Indicates if this thread should shut down */
	private boolean shutdown;

	/** The socket to be monitored by this listener. */
	private DatagramSocket socket;

	/** The packet to be filled with received data. */
	private DatagramPacket packet;

	/**
	 * Creates a new listener thread to monitor a socket.
	 * 
	 * @param socket
	 *            the socket to be monitored by this listener.
	 * @param packet
	 *            the packet to be filled with received data.
	 */
	public myListener(/* UDP_chat me, */DatagramSocket socket,
			DatagramPacket packet) {
		this.shutdown = false;
		this.socket = socket;
		this.packet = packet;
	}

	/**
	 * The run method monitors the socket for incoming data, printing whatever
	 * it gets...
	 */
	public void run() {
		while (!shouldShutdown()) {
			try {
				socket.receive(packet);
				System.out.println(new String(packet.getData(), 0, packet
						.getLength()));
			} catch (Exception e) {
				e.printStackTrace();
				break; // terminate thread
			}
		}
	}

	/**
	 * Check if we should shutdown the listener thread.
	 * 
	 * @return true if we should shutdown; false otherwise.
	 */
	public synchronized boolean shouldShutdown() {
		return shutdown;
	}

	/**
	 * Notify this listener thread that it should shutdown.
	 */
	public synchronized void shutdown() {
		shutdown = true;
	}

}

/////////////////////////////////////////////////////////////////
// public void receiveMsg() {
// try {
// inPacket = new DatagramPacket(inBuf, inBuf.length);
// InSocket.receive(inPacket);
// String msg = new String(inBuf, 0, inPacket.getLength());
// if (msg.equalsIgnoreCase("quit")) {
// System.exit(0);
// }
// System.out.println("Received: " + msg);
// inPacket.setLength(inBuf.length);
// } catch (Exception e) {
// System.out.println(e);
// }
// }
